Add centralized banner system with OS messaging support#14708
Add centralized banner system with OS messaging support#14708
Conversation
Fetches a markdown message from the DaaS-published GCS bucket, renders the bleached headline and optional expanded section through the existing additional_banners template loop. Cached for 1h; any fetch/parse failure silently yields no banner. No Django settings introduced — disabling the banner requires forking. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single newlines in the expanded body now render as <br>, so authored markdown lays out multi-line. Module folded into the existing dojo/announcement/ app and test patch paths updated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Anchor-based toggle picked up Bootstrap alert link styles and a lingering focus outline after click, which showed as a stray glyph next to the caret. A plain <button type="button"> avoids link decoration entirely; focus outline and transition are also dropped so the caret flips instantly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Migrate all promotional messaging to the additional_banners context processor pattern. Product announcements now store banners in the session for rendering via the unified template loop. Each banner carries a source field (os, product_announcement) so downstream repos can filter by origin. - Remove DD_CREATE_CLOUD_BANNER setting and env var entirely - Repurpose ProductAnnouncementManager to use session-based banners - Remove evaluate_pro_proposition celery task and beat schedule - Remove create_announcement_banner from initialization command - Simplify announcement signal to remove cloud-specific logic - Add SHOW_PLG_LINK context variable for PLG menu item control - Rename os-banner-* CSS classes to generic banner-* classes - Add data-source attribute to banner template markup - Switch OS message bucket URL from dev to prod - Add 52 tests covering context processor and product announcements Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
This pull request introduces potential Cross-Site Scripting risks: session-created banners are marked safe and later rendered with the template |safe filter without proper sanitization (product_announcements.py and template), while only the OS-fetched banner path uses bleach sanitization, leaving session-stored/interpolated content able to inject HTML/JS. Review and ensure all banner content is sanitized (or avoid mark_safe/|safe) before rendering to prevent XSS.
🔴 Potential Cross-Site Scripting in
|
| Vulnerability | Potential Cross-Site Scripting |
|---|---|
| Description | Template uses the safe filter to render banner.message and banner.expanded_html ({{ banner.messagesafe }}, {{ banner.expanded_htmlsafe }}), which disables Django auto-escaping. We must confirm whether the values in additional_banners are sanitized before being marked safe. |
django-DefectDojo/dojo/templates/base.html
Lines 673 to 690 in 6a30549
🟠 Potential Cross-Site Scripting in dojo/context_processors.py (drs_1b98f186)
| Vulnerability | Potential Cross-Site Scripting |
|---|---|
| Description | additional_banners may include data from two sources: (1) get_os_banner() which fetches remote Markdown, renders it to HTML via markdown.markdown and then sanitizes with bleach.clean into 'message' and 'expanded_html'; (2) arbitrary dicts stored in request.session by product_announcement.add_session_banner (message field created from str((message))) and later popped and added directly to context. The template renders banner.message and banner.expanded_html with the safe filter, bypassing Django auto-escaping. We must ensure those values are sanitized for the HTML context before marking safe; only the OS banner path applies bleach sanitization. Session-stored banners are not sanitized before being marked safe in the template, allowing user-controlled input to reach the rendering sink without escaping. |
django-DefectDojo/dojo/context_processors.py
Lines 36 to 67 in 6a30549
🟠 Potential Cross-Site Scripting in dojo/product_announcements.py (drs_bbe0400c)
| Vulnerability | Potential Cross-Site Scripting |
|---|---|
| Description | mark_safe is used when building a session banner message: mark_safe(f"{self.base_message} {self.ui_outreach}") — this bypasses Django auto-escaping. If any interpolated content can be attacker-controlled, it would reach a template and be rendered without escaping, causing XSS. |
django-DefectDojo/dojo/product_announcements.py
Lines 34 to 35 in 6a30549
We've notified @mtesauro.
Comment to provide feedback on these findings.
Report false positive: @dryrunsecurity fp [FINDING ID] [FEEDBACK]
Report low-impact: @dryrunsecurity nit [FINDING ID] [FEEDBACK]
Example: @dryrunsecurity fp drs_90eda195 This code is not user-facing
All finding details can be found in the DryRun Security Dashboard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
valentijnscholten
left a comment
There was a problem hiding this comment.
What is the reason for the server-side caching? Is it for client side performance or to save on outgoing traffic on the bucket? Wouldn't it be much easier to just let the browser load it straight from the bucket and configure the bucket with an appropriate Cache-Control header? This way it would also work if the server is inside some network that is not allowed to egress to GCS.
|
There is some formatting server side before the raw content is sent to the browser. Seems like it would be less performant to do that computation in the browser on every request rather than once every few through the cache |
valentijnscholten
left a comment
There was a problem hiding this comment.
Yeah I don't understand why so much processing is needed. The content is in your control so I would expect it to be tailer made and would only need a nh3 or dompurify sanitize as assurance for OS users/admins.
displays it via the existing additional_banners template loop. Cached for 1 hour; fetch failures silently yield no banner.
context processor pattern. Both OS messages and product announcements now flow through the same rendering pipeline, each tagged with a source field
(os, product_announcement).
processor and rendered in the unified template loop.